package com.pf.utils;

import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.*;

/**
 * @author PanFei
 * @version 1.0.0
 * @createTime 2021/9/8
 */
@Slf4j
public class ESignUtils {

    public static void main(String[] args) throws Exception {
        // 服务端为客户端提供的唯一标识的固定值
        String appId = "pay_1234";
        String appSecret = "abc123";
        String token = "123456789";
        Map<String, String> reqParams = new HashMap<>();
        reqParams.put("appId", appId);
        reqParams.put("requestId", UUID.randomUUID().toString());
        reqParams.put("timestamp", System.currentTimeMillis() + "");
    }

    private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();

    /**
     * 生成签名
     *
     * @param appSecret 服务端为客户端提供的唯一标识的密码固定值
     * @param publicParams 请求接口url后面拼接的参数，如 (APP-ID,APP-REQUEST-ID,APP-TIMESTAMP,APP-SIGN)
     * @param publicParams   业务参数，如reqBody中的json数据
     * @return
     * @throws Exception
     */
    public static String sign(String appSecret, Map<String, String> publicParams, Object body) throws Exception {
        // 为reqParams的key排序
//        List<String> keys = publicParams.keySet().stream().filter(key -> !"sign".equals(key)).sorted().collect(Collectors.toList());
        List<String> keys = new ArrayList<>();
        Set<String> strings = publicParams.keySet();
        for (String key : strings) {
            if (!"sign".equals(key)) {
                keys.add(key);
            }
        }
        Collections.sort(keys);


        // 将reqParams参数名和值拼接在一起
        StringBuilder reqParamStr = new StringBuilder();
        reqParamStr.append(appSecret);
        for (String key : keys) {
            String value = publicParams.get(key);
            if (StringUtils.isNoneBlank(key, value)) {
                reqParamStr.append(key).append(publicParams.get(key));
            }
        }
        String reqBodyStr = body instanceof String ? (String) body : OBJECT_MAPPER.writeValueAsString(body);
        if (StringUtils.isNotBlank(reqBodyStr)) {
            reqParamStr.append(reqBodyStr);
        }
        // 使用MD5加密
        byte[] bytes;
        MessageDigest md5 = null;
        try {
            md5 = MessageDigest.getInstance("MD5");
        } catch (NoSuchAlgorithmException ignored) {
            throw new Exception(ignored);
        }
        bytes = md5.digest(reqParamStr.toString().getBytes("UTF-8"));
        // 第四步：把二进制转化为大写的十六进制
        StringBuilder sign = new StringBuilder();
        for (byte b : bytes) {
            String hex = Integer.toHexString(b & 0xFF);
            if (hex.length() == 1) {
                sign.append("0");
            }
            sign.append(hex.toUpperCase());
        }
        return sign.toString();
    }

}
